// pages/devConn/devConn.js

var app = getApp();
var util = require('../../utils/util.js');  

//用于显示全部设备
let all_devices = {}
let showdata={}   //用于存储点击特性uuid时传递的数据

function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}

Page({

  /**
   * 页面的初始数据
   */
  data: {
    leftPosition: 0,    
    devices: [],
    bluet_conn_flag: false,
    chs: [],
    scan_status: false,          //设置蓝牙扫描按钮的状态
    btn_scan_name: '开始扫描',    //设置蓝牙扫描按钮的显示名称
    btn_scan_status: false,      //设置开始扫描按钮的状态
    btn_stop_scan_status: false, //设置停止扫描按钮的状态
    btn_kill_service_status:true,//设置结束本次服务按钮的状态
    btn_conn_status: true,       //设置断开连接按钮的状态
    receive_data:'',             //存储接收到的数据
    lineBreak: false,            //数据换行
    isHexShow: false,            //16进制显示

    characterRWN_conn_flag:false,    //判断支持RWN的特性UUID是否连接
    characterRWN_UUID:'',       //支持RWN的特性UUID
    serviceRWN_UUID:'',         //包含支持支持RWN特性UUID的服务UUID
    time:'',    //时间日期
    reload_flag:false,  //重新加载标志
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

    console.log("this.reload:"+this.reload_flag)
    if(this.reload_flag) //重新加载标志为true时才进行重连
    {
      wx.showLoading({
        mask: true,
        title: '连接中...',
      })
      setTimeout(function () {
        wx.hideLoading()
      }, 1000)
  
      let that = this
      let deviceId = this.data.deviceId

      wx.createBLEConnection({
        deviceId,
        success: (res) => {
          app.globalData.isConnect = true
          that.getBLEDeviceServices(deviceId)

          this.setData({
            reload_flag:true,
          })
        },
        fail: (res) => {
          console.log(res)
          setTimeout(() => {
            wx.hideLoading({
              complete: (res) => {
                that.setData({
                  leftPosition: 0
                })
                that.showFail()
              },
            })
          }, 400)
        }
      })
    }    
  },

  /**
   * 连接失败处理
   */
  showFail() {
    let that = this
    wx.showToast({
      title: '连接失败',
      icon: 'none',
      duration: 1000
    })
    that.closeBLEConnection()
    that.setData({
      characteristicUUIDs: null,
      serviceUUIDs: null,
      characterRWN_conn_flag: false,
    })
    app.globalData.characterRWN_conn_flag = false
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
      console.log("个人信息如下：")
      console.log(app.globalData.userInfo)
      this.getTabBar().setData({
        selected: 1
      })
    }

    if(app.globalData.bluet_conn_flag)
    {
      this.onrefresh(this.showdata)
    }
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },

  /**
   * 重新加载
   * @param {*} res 
   */
  reload(res) {
    this.setData({
      reload_flag:true,
    })
    this.onReady()
  },

  /**
   * 
   * 左边列表点击服务UUID显示右边的特性UUID
   * @param {*} res 
   */
  leftClick(res) {
    let index = res.target.dataset.index
    if (index != this.data.leftPosition) {
      let lastPosition = this.data.leftPosition
      this.setData({
        leftPosition: index
      })
      wx.showLoading({  //必须配合hideLoading使用才能关闭
        mask: true,
        title: '请求中...',
      })
      setTimeout(function () {
        wx.hideLoading()
      }, 1000)
      this.getBLEDeviceCharacteristics(this.data.deviceId, this.data.serviceUUIDs[index].uuid, lastPosition)

    }
  },

  /**
   * 点击右边列表 选择特性UUID进行连接，只有特定的特性UUID才能支持读写
   * @param {*} res 
   */
  rightClick(res){
    let that = this
    let index = res.target.dataset.index
    let characteristicsUUID = that.data.characteristicUUIDs[index]
    let deviceId = that.data.deviceId
    let serviceUUID = that.data.serviceUUIDs[that.data.leftPosition]

    let obj = {
      characteristicsUUID: characteristicsUUID,
      deviceId: deviceId,
      serviceUUID: serviceUUID,
      deviceName:that.data.title,
      needClose:false
    }
    this.showdata=JSON.stringify(obj);
    this.onrefresh(this.showdata)
  },

  /**
   * 监听特征值  接收数据
   * @param {*} data 
   */
  onrefresh(data){
    var that = this
    let deviceId = JSON.parse(data).deviceId
    let serviceId = JSON.parse(data).serviceUUID.uuid
    let characteristicId = JSON.parse(data).characteristicsUUID.uuid

    // 必须在这里的回调才能获取
    wx.onBLECharacteristicValueChange(function (res) {
      var TIME = util.formatTime(new Date());
      let hexStr = ab2hex(res.value)
      // if (!that.isHexShow) { //16进制显示
      //   hexStr = that.hexCharCodeToStr(hexStr)
      // }

      // let currentData = this.receive_data += hexStr
      // if (that.lineBreak) {  //换行显示
      //   currentData += '\n'
      // }
      that.setData({
        receive_data: that.hexCharCodeToStr(hexStr),
        time: TIME,
      })
      app.globalData.receive_data = that.data.receive_data

      console.log("app.globalData.receive_data:"+app.globalData.receive_data)
    })

    let properties = JSON.parse(data).characteristicsUUID.properties//特性UUID属性
    if (properties.indicate || (properties.notify && properties.read && properties.write)) { 
      app.globalData.characterRWN_conn_flag = true
      that.setData({
          canWrite: true,
          characterRWN_conn_flag: true,
          characterRWN_UUID: characteristicId,
          serviceRWN_UUID: serviceId,
      })
        console.log("notifyBLECharacteristicValueChange成功启用!")
        wx.notifyBLECharacteristicValueChange({
          deviceId,
          serviceId,
          characteristicId,
          state:true,
          success(res) {
            console.log('notifyBLECharacteristicValueChange success', res.errMsg)  
          }
        })
    }else{
      wx.showToast({
        title: '此服务不支持读写!',
        icon:'error',
        duration:1500, //提示延迟时间
      })
    }

  },

  /**
   * 打开蓝牙适配器
   */
  openBluetoothAdapter() {
    wx.openBluetoothAdapter({  //判断蓝牙是否打开
      success: (res) => {
        console.log('蓝牙适配器已打开', res)
        this.startBluetoothDevicesDiscovery()
      },
      fail: (res) => {
        if(res)
        wx.showModal({
          showCancel: false,  //不显示取消按钮
          content: '请先开启手机蓝牙，然后重试！'
        })
      }
    })
  },
  getBluetoothAdapterState() {
    wx.getBluetoothAdapterState({
      success: (res) => {
        console.log('getBluetoothAdapterState', res)
        if (res.discovering) {
          this.onBluetoothDeviceFound()
        } else if (res.available) {
          this.startBluetoothDevicesDiscovery()
        }
      }
    })
  },

  /**
   * 蓝牙扫描
   */
  startBluetoothDevicesDiscovery() {    
      if (this._discoveryStarted) {
        return
      }
      this._discoveryStarted = true //第一次点击扫描之后设置为true，防止重复点击
      wx.startBluetoothDevicesDiscovery({
        allowDuplicatesKey: true, //允许重复上报同一设备
        interval:0,   //上报设备的间隔。0 表示找到新设备立即上报，其他数值根据传入的间隔上报
        powerLevel: "high",   //扫描模式，越高扫描越快,且越耗电
        success: (res) => {
          console.log('开始搜寻蓝牙设备', res)
          this.setData({
            scan_status: true,
            btn_scan_name: '正在扫描',
            btn_kill_service_status: false,
          })
          this.onBluetoothDeviceFound()
        },
      })
    
  },
  /**
   * 停止蓝牙设备搜索
   */
  stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery()  //停止蓝牙设备扫描
    this._discoveryStarted = false  //停止扫描之后设置为false，以备再次点击扫描可以继续进行蓝牙设备扫描
    this.setData({
      scan_status:false,
      btn_scan_name: '开始扫描'
    })
  },

  /**
   * 监听蓝牙设备 并回调
   */
  onBluetoothDeviceFound() {
    wx.onBluetoothDeviceFound((res) => {
      res.devices.forEach(device => {
        all_devices[device.deviceId] = device.name
        if (!device.name && !device.localName) {
          return
        }
        const foundDevices = this.data.devices
        const idx = inArray(foundDevices, 'deviceId', device.deviceId)
        const data = {}
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device
        } else {
          data[`devices[${idx}]`] = device
        }
        this.setData(data)
        this.setData({
          bluetooth_list: all_devices,            
        })
      })
    })
  },

  /**
   * 切换服务，重新选择特性UUID
   * @param {*} e 
   */
  switchService(e){
    wx.showLoading({
      mask: true,
      title: '请求中...',
    })    
    this.closeBLEConnection();  //先关闭蓝牙
    const ds = e.currentTarget.dataset
    const deviceId = ds.deviceId  //uuid
    const name = ds.name

    wx.createBLEConnection({
      deviceId,
      success: (res) => {
        app.globalData.bluet_conn_flag = true,
        this.getBLEDeviceServices(deviceId) //获取 Service UUID
        this.setData({
          bluet_conn_flag: true,  //蓝牙连接成功
          name,
          deviceId, 
          //改变按钮状态
          btn_scan_status: true,
          btn_stop_scan_status: true,
          btn_conn_status: false,
        })

        setTimeout(function () {
          wx.hideLoading()
        }, 1000)

      },
      
      fail(e) {        
      }
    })
  },

  /**
   * 蓝牙连接
   * @param {*} e 
   */
  createBLEConnection(e) {
    const ds = e.currentTarget.dataset
    const deviceId = ds.deviceId  //uuid
    const name = ds.name
    wx.createBLEConnection({
      deviceId,
      success: (res) => {
        wx.showToast({
          title: '连接成功',  
          duration:500, //提示延迟时间        
        })
        app.globalData.bluet_conn_flag = true,
        this.getBLEDeviceServices(deviceId) //获取 Service UUID

        this.setData({
          bluet_conn_flag: true,  //蓝牙连接成功
          name,
          deviceId, 
          //改变按钮状态
          btn_scan_status: true,
          btn_stop_scan_status: true,
          btn_conn_status: false,
        })        
        
        this.stopBluetoothDevicesDiscovery()  //连接之后停止蓝牙搜索
      },
      fail(e) {
        wx.hideLoading({
          success: (res) => {},
        })
        console.error(e)
        switch (e.errCode) {
          case 0:
            wx.showToast({
              title: '连接成功',
            })
            break
          case -1:
            wx.showToast({
              title: '设备已连接',
            })
            break
          case 10000:
            wx.showToast({
              title: '请重新扫描蓝牙适配器',
            })
            break
          case 10003:
            wx.showToast({
              title: '连接失败',
              icon: 'none'
            })
            break
          case 10012:
            wx.showToast({
              title: '连接超时',
              icon: 'none'
            })
            break
          default:
            wx.showToast({
              title: e.errMsg,
              icon: 'none'
            })
        }
      }
    })
    
  },

  /**
   * 关闭蓝牙连接
   */
  closeBLEConnection() {
    wx.closeBLEConnection({
      deviceId: this.data.deviceId,      
    })
    app.globalData.bluet_conn_flag = false
    app.globalData.characterRWN_conn_flag = false
    this.setData({
      bluet_conn_flag: false,
      chs: [],
      canWrite: false,
      btn_scan_status:false,
      btn_stop_scan_status:false,
      btn_conn_status: true,     
      characterRWN_conn_flag: false, 
    })
  },
  /**
   * 获取 service UUID
   * @param {*} deviceId 
   */
  getBLEDeviceServices(deviceId) {
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        let serviceUUIDs = new Array()  //存储服务UUID
        console.log('deviceId:'+deviceId) 
        console.log('res.services.length:'+res.services.length)   //3个service uuid
        for (let i = 0; i < res.services.length; i++) {
          console.log('res.services['+i+'].uuid: '+res.services[i].uuid)
          if (res.services[i].isPrimary) {      //判断服务是否为主服务
            serviceUUIDs.push(res.services[i])
          }
        }
        this.setData({
          serviceUUIDs: serviceUUIDs
        })
        this.getBLEDeviceCharacteristics(deviceId, res.services[this.data.leftPosition].uuid,this.data.leftPosition)
      },
      fail: (res) => {
        console.log('fail', res)
        wx.hideLoading({
          complete: (res) => {
            setTimeout(() => {
              wx.hideLoading({
                complete: (res) => {
                  this.setData({
                    leftPosition: 0
                  })
                  wx.hideLoading({
                    complete: (res) => {
                      this.showFail()
                    },
                  })
                },
              })
            }, 400)
          },
        })
      }
    })
  },

  /**
   * 获取蓝牙特性UUID信息
   * @param {*} deviceId   
   * @param {*} serviceId 
   * @param {*} lastPosition 
   */
  getBLEDeviceCharacteristics(deviceId, serviceId, lastPosition) {
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {       
        console.log('getBLEDeviceCharacteristics success', res.characteristics)                  
        console.log('serviceId:'+serviceId)
  
        let characteristicUUIDs = new Array()
        for (let i = 0; i < res.characteristics.length; i++) {
          let item = res.characteristics[i]
          characteristicUUIDs.push(item)
        }
        this.setData({
          characteristicUUIDs: characteristicUUIDs
        })
        console.log("=========================")
        console.log(characteristicUUIDs)
        console.log("=========================")
      },
      fail(res) {
          console.log(res)
          setTimeout(() => {
            wx.hideLoading({
              complete: (res) => {
                this.setData({
                  leftPosition: lastPosition
                })
                this.showFail()
              },
            })
          }, 400)
        }
    })
  },
  writeBLECharacteristicValue() {
    // 向蓝牙设备发送一个0x00的16进制数据
    let buffer = new ArrayBuffer(1)
    let dataView = new DataView(buffer)
    dataView.setUint8(0, Math.random() * 255 | 0)
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._deviceId,
      characteristicId: this._characteristicId,
      value: buffer,
    })
  },

  /**
   * 关闭蓝牙适配器服务
   */
  closeBluetoothAdapter() {
    wx.closeBluetoothAdapter()
    app.globalData.bluet_conn_flag = false
    app.globalData.characterRWN_conn_flag = false
    this._discoveryStarted = false
    this.setData({
      bluet_conn_flag: false,
      btn_scan_name: '开始扫描',
      scan_status: false, 
      btn_conn_status: true,
      btn_scan_status: false,
      btn_stop_scan_status: false,
      characterRWN_conn_flag: false,
    })
  },

  /**
   * 16进制转字符串
   * @param {*} hexCharCodeStr 
   */
  hexCharCodeToStr(hexCharCodeStr) {
    var trimedStr = hexCharCodeStr.trim();
    var rawStr =
      trimedStr.substr(0, 2).toLowerCase() === "0x" ?
      trimedStr.substr(2) :
      trimedStr;
    var len = rawStr.length;
    if (len % 2 !== 0) {
      alert("Illegal Format ASCII Code!");
      return "";
    }
    var curCharCode;
    var resultStr = [];
    for (var i = 0; i < len; i = i + 2) {
      curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
      resultStr.push(String.fromCharCode(curCharCode));
    }
    // console.log(resultStr.join(""));
    return resultStr.join("");
  },
})